home *** CD-ROM | disk | FTP | other *** search
/ Languguage OS 2 / Languguage OS II Version 10-94 (Knowledge Media)(1994).ISO / gnu / gas_251.zip / bin_251 / opcodes / mips-dis.c < prev    next >
C/C++ Source or Header  |  1994-06-28  |  7KB  |  275 lines

  1. /* Print mips instructions for GDB, the GNU debugger, or for objdump.
  2.    Copyright 1989, 1991, 1992 Free Software Foundation, Inc.
  3.    Contributed by Nobuyuki Hikichi(hikichi@sra.co.jp).
  4.  
  5. This file is part of GDB.
  6.  
  7. This program is free software; you can redistribute it and/or modify
  8. it under the terms of the GNU General Public License as published by
  9. the Free Software Foundation; either version 2 of the License, or
  10. (at your option) any later version.
  11.  
  12. This program is distributed in the hope that it will be useful,
  13. but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15. GNU General Public License for more details.
  16.  
  17. You should have received a copy of the GNU General Public License
  18. along with this program; if not, write to the Free Software
  19. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
  20.  
  21. #include <ansidecl.h>
  22. #include "sysdep.h"
  23. #include "dis-asm.h"
  24. #include "opcode/mips.h"
  25.  
  26. /* Mips instructions are never longer than this many bytes.  */
  27. #define MAXLEN 4
  28.  
  29. /* FIXME: This should be shared with gdb somehow.  */
  30. #define REGISTER_NAMES     \
  31.     {    "zero",    "at",    "v0",    "v1",    "a0",    "a1",    "a2",    "a3", \
  32.     "t0",    "t1",    "t2",    "t3",    "t4",    "t5",    "t6",    "t7", \
  33.     "s0",    "s1",    "s2",    "s3",    "s4",    "s5",    "s6",    "s7", \
  34.     "t8",    "t9",    "k0",    "k1",    "gp",    "sp",    "s8",    "ra", \
  35.     "sr",    "lo",    "hi",    "bad",    "cause","pc",    \
  36.     "f0",   "f1",   "f2",   "f3",   "f4",   "f5",   "f6",   "f7", \
  37.     "f8",   "f9",   "f10",  "f11",  "f12",  "f13",  "f14",  "f15", \
  38.     "f16",  "f17",  "f18",  "f19",  "f20",  "f21",  "f22",  "f23",\
  39.     "f24",  "f25",  "f26",  "f27",  "f28",  "f29",  "f30",  "f31",\
  40.     "fsr",  "fir",  "fp",   "inx",  "rand", "tlblo","ctxt", "tlbhi",\
  41.     "epc",  "prid"\
  42.     }
  43.  
  44. static CONST char * CONST reg_names[] = REGISTER_NAMES;
  45.  
  46. /* subroutine */
  47. static void
  48. print_insn_arg (d, l, pc, info)
  49.      const char *d;
  50.      register unsigned long int l;
  51.      bfd_vma pc;
  52.      struct disassemble_info *info;
  53. {
  54.   int delta;
  55.  
  56.   switch (*d)
  57.     {
  58.     case ',':
  59.     case '(':
  60.     case ')':
  61.       (*info->fprintf_func) (info->stream, "%c", *d);
  62.       break;
  63.  
  64.     case 's':
  65.     case 'b':
  66.     case 'r':
  67.     case 'v':
  68.       (*info->fprintf_func) (info->stream, "$%s",
  69.                  reg_names[(l >> OP_SH_RS) & OP_MASK_RS]);
  70.       break;
  71.  
  72.     case 't':
  73.     case 'w':
  74.       (*info->fprintf_func) (info->stream, "$%s",
  75.                  reg_names[(l >> OP_SH_RT) & OP_MASK_RT]);
  76.       break;
  77.  
  78.     case 'i':
  79.     case 'u':
  80.       (*info->fprintf_func) (info->stream, "%d",
  81.             (l >> OP_SH_IMMEDIATE) & OP_MASK_IMMEDIATE);
  82.       break;
  83.  
  84.     case 'j': /* same as i, but sign-extended */
  85.     case 'o':
  86.       delta = (l >> OP_SH_DELTA) & OP_MASK_DELTA;
  87.       if (delta & 0x8000)
  88.     delta |= ~0xffff;
  89.       (*info->fprintf_func) (info->stream, "%d",
  90.                  delta);
  91.       break;
  92.  
  93.     case 'k':
  94.       (*info->fprintf_func) (info->stream, "0x%x",
  95.                  (unsigned int) ((l >> OP_SH_CACHE)
  96.                          & OP_MASK_CACHE));
  97.       break;
  98.  
  99.     case 'a':
  100.       (*info->print_address_func)
  101.     (((pc & 0xF0000000) | (((l >> OP_SH_TARGET) & OP_MASK_TARGET) << 2)),
  102.      info);
  103.       break;
  104.  
  105.     case 'p':
  106.       /* sign extend the displacement */
  107.       delta = (l >> OP_SH_DELTA) & OP_MASK_DELTA;
  108.       if (delta & 0x8000)
  109.     delta |= ~0xffff;
  110.       (*info->print_address_func)
  111.     ((delta << 2) + pc + 4,
  112.      info);
  113.       break;
  114.  
  115.     case 'd':
  116.       (*info->fprintf_func) (info->stream, "$%s",
  117.                  reg_names[(l >> OP_SH_RD) & OP_MASK_RD]);
  118.       break;
  119.  
  120.     case 'z':
  121.       (*info->fprintf_func) (info->stream, "$%s", reg_names[0]);
  122.       break;
  123.  
  124.     case '<':
  125.       (*info->fprintf_func) (info->stream, "0x%x",
  126.                  (l >> OP_SH_SHAMT) & OP_MASK_SHAMT);
  127.       break;
  128.  
  129.     case 'c':
  130.       (*info->fprintf_func) (info->stream, "0x%x",
  131.                  (l >> OP_SH_CODE) & OP_MASK_CODE);
  132.       break;
  133.  
  134.     case 'C':
  135.       (*info->fprintf_func) (info->stream, "0x%x",
  136.                  (l >> OP_SH_COPZ) & OP_MASK_COPZ);
  137.       break;
  138.  
  139.     case 'B':
  140.       (*info->fprintf_func) (info->stream, "0x%x",
  141.                  (l >> OP_SH_SYSCALL) & OP_MASK_SYSCALL);
  142.       break;
  143.  
  144.     case 'S':
  145.     case 'V':
  146.       (*info->fprintf_func) (info->stream, "$f%d",
  147.                  (l >> OP_SH_FS) & OP_MASK_FS);
  148.       break;
  149.  
  150.     case 'T':
  151.     case 'W':
  152.       (*info->fprintf_func) (info->stream, "$f%d",
  153.                  (l >> OP_SH_FT) & OP_MASK_FT);
  154.       break;
  155.  
  156.     case 'D':
  157.       (*info->fprintf_func) (info->stream, "$f%d",
  158.                  (l >> OP_SH_FD) & OP_MASK_FD);
  159.       break;
  160.  
  161.     case 'E':
  162.       (*info->fprintf_func) (info->stream, "$%d",
  163.                  (l >> OP_SH_RT) & OP_MASK_RT);
  164.       break;
  165.  
  166.     case 'G':
  167.       (*info->fprintf_func) (info->stream, "$%d",
  168.                  (l >> OP_SH_RD) & OP_MASK_RD);
  169.       break;
  170.  
  171.     default:
  172.       (*info->fprintf_func) (info->stream,
  173.                  "# internal error, undefined modifier(%c)", *d);
  174.       break;
  175.     }
  176. }
  177.  
  178. /* Print the mips instruction at address MEMADDR in debugged memory,
  179.    on using INFO.  Returns length of the instruction, in bytes, which is
  180.    always 4.  BIGENDIAN must be 1 if this is big-endian code, 0 if
  181.    this is little-endian code.  */
  182.  
  183. int
  184. _print_insn_mips (memaddr, word, info)
  185.      bfd_vma memaddr;
  186.      struct disassemble_info *info;
  187.      unsigned long int word;
  188. {
  189.   register const struct mips_opcode *op;
  190.   static boolean init = 0;
  191.   static const struct mips_opcode *mips_hash[OP_MASK_OP + 1];
  192.  
  193.   /* Build a hash table to shorten the search time.  */
  194.   if (! init)
  195.     {
  196.       int i;
  197.  
  198.       for (i = 0; i <= OP_MASK_OP; i++)
  199.     {
  200.       for (op = mips_opcodes; op < &mips_opcodes[NUMOPCODES]; op++)
  201.         {
  202.           if (op->pinfo == INSN_MACRO)
  203.         continue;
  204.           if ((i << OP_SH_OP) == (op->match & (OP_MASK_OP << OP_SH_OP)))
  205.         {
  206.           mips_hash[i] = op;
  207.           break;
  208.         }
  209.         }
  210.         }
  211.  
  212.       init = 1;
  213.     }
  214.  
  215.   op = mips_hash[(word >> OP_SH_OP) & OP_MASK_OP];
  216.   if (op != NULL)
  217.     {
  218.       for (; op < &mips_opcodes[NUMOPCODES]; op++)
  219.     {
  220.       if (op->pinfo != INSN_MACRO && (word & op->mask) == op->match)
  221.         {
  222.           register const char *d;
  223.  
  224.           (*info->fprintf_func) (info->stream, "%s", op->name);
  225.  
  226.           d = op->args;
  227.           if (d != NULL)
  228.         {
  229.           (*info->fprintf_func) (info->stream, " ");
  230.           for (; *d != '\0'; d++)
  231.             print_insn_arg (d, word, memaddr, info);
  232.         }
  233.  
  234.           return 4;
  235.         }
  236.     }
  237.     }
  238.  
  239.   /* Handle undefined instructions.  */
  240.   (*info->fprintf_func) (info->stream, "0x%x", word);
  241.   return 4;
  242. }
  243.  
  244. int
  245. print_insn_big_mips (memaddr, info)
  246.      bfd_vma memaddr;
  247.      struct disassemble_info *info;
  248. {
  249.   bfd_byte buffer[4];
  250.   int status = (*info->read_memory_func) (memaddr, buffer, 4, info);
  251.   if (status == 0)
  252.     return _print_insn_mips (memaddr, bfd_getb32 (buffer), info);
  253.   else
  254.     {
  255.       (*info->memory_error_func) (status, memaddr, info);
  256.       return -1;
  257.     }
  258. }
  259.  
  260. int
  261. print_insn_little_mips (memaddr, info)
  262.      bfd_vma memaddr;
  263.      struct disassemble_info *info;
  264. {
  265.   bfd_byte buffer[4];
  266.   int status = (*info->read_memory_func) (memaddr, buffer, 4, info);
  267.   if (status == 0)
  268.     return _print_insn_mips (memaddr, bfd_getl32 (buffer), info);
  269.   else
  270.     {
  271.       (*info->memory_error_func) (status, memaddr, info);
  272.       return -1;
  273.     }
  274. }
  275.